package com.fingard.dsp.bank.directbank.citi01.util;

import com.alibaba.fastjson.JSON;
import com.fingard.FGBiz;
import com.fingard.diagnostics.LogHelper;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.net.ConnState;
import com.fingard.net.WebRequest;
import com.fingard.net.https.HttpsHandler;
import com.fingard.text.StringHelper;
import com.sun.net.ssl.KeyManagerFactory;
import com.sun.net.ssl.SSLContext;
import com.sun.net.ssl.TrustManagerFactory;
import com.sun.net.ssl.TrustManager;
import sun.misc.BASE64Encoder;
import javax.net.ssl.*;
import java.io.*;
import java.net.*;
import java.security.KeyStore;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;

public class HttpClient extends DirectBase {

    private final static String charset = "UTF-8";

    /**
              * 客户端证书设置
     */
    protected static String clientCertPwd = "123456";// 客户端证书密码
    protected static String clientCertPath = "E:\\ssl\\2019_xicha.jks";
    protected static String clientKeyType = "jks";
    private final static String PFX_PATH = "E:\\ssl\\apiclient_cert.p12";    //客户端证书路径
    private final static String PFX_PWD = "123456";    //客户端证书密码

    /**
              * 服务端证书设置
     */
    protected String truestCertPwd = "123456";
    protected String  trustCertPath ="E:\\ssl\\hq.com.cer";
    protected String truestKeyType = "cer";

    private static SSLContext sslContext;

    private static HttpsURLConnection httpConnection= null;


    /**
     * post方法
     */
    public static   String post(String tmpToWrite, String requestAddr,String authorization) throws Exception{
    	String retStr = "";
        StringBuffer sb = null;

        OutputStream os = null;
        InputStream fis = null;
        BufferedInputStream bis = null;

        InputStream is = null;
        BufferedReader br = null;
        try {
            if (sslContext == null) {
                sslContext = SSLContext.getInstance("TLSv1.2");
                KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
                TrustManagerFactory tmf = TrustManagerFactory
                        .getInstance("SunX509");

                KeyStore keyStore = KeyStore.getInstance(clientKeyType);
                keyStore.load(new FileInputStream(clientCertPath),
                        clientCertPwd.toCharArray());
                kmf.init(keyStore, clientCertPwd.toCharArray());
                TrustManager[] tm = { new MyX509TrustManager() };
                sslContext.init(kmf.getKeyManagers(),tm, null);
                HttpsHandler.trustAllHttpsCertificates();
                HostnameVerifier hv = new HostnameVerifier() {
					public boolean verify(String urlHostName, SSLSession session) {
						return true;
					}

				};
				HttpsURLConnection.setDefaultHostnameVerifier(hv);
            }
            System.setProperty("sun.net.http.allowRestrictedHeaders", "true");
            URL url = new URL(null,requestAddr, new sun.net.www.protocol.https.Handler());
            httpConnection =  (HttpsURLConnection) url.openConnection();
            httpConnection.setInstanceFollowRedirects(false);
            httpConnection.setUseCaches(false);
            httpConnection.setConnectTimeout(60000);

            httpConnection.setDoOutput(true);
            httpConnection.setDoInput(true);
            httpConnection.setRequestMethod("GET");
            httpConnection.setRequestProperty("Accept-Encoding", "gzip,deflate");
            httpConnection.addRequestProperty("Content-Type", "application/xml");
            httpConnection.setRequestProperty("Authorization", "Bearer "+authorization.replaceAll("(\\r|\\n)", ""));
            //httpConnection.setRequestProperty("Content-Length", length);
            httpConnection.setRequestProperty("Host", "tts.sandbox.apib2b.citi.com");
            httpConnection.setRequestProperty("Connection", "Keep-Alive");
            httpConnection.setRequestProperty("User-Agent", "Apache-HttpClient/4.1.1");
            httpConnection.setRequestProperty("Accept-Charset", charset);
            httpConnection.setSSLSocketFactory(sslContext.getSocketFactory());
            httpConnection.addRequestProperty("endToEndId",tmpToWrite);
            httpConnection.addRequestProperty("GlobalTranNo","2439592460234");
            httpConnection.connect();

            is = httpConnection.getInputStream();
            br = new BufferedReader(new InputStreamReader(is, "GBK"));
            sb = new StringBuffer();
            String line;
            while ((line = br.readLine()) != null) {
                sb.append(line);
            }
            retStr = sb.toString();
        } catch (Exception e) {
            System.out.println(JSON.toJSONString(httpConnection.getHeaderFields()));
            System.out.println(JSON.toJSONString(httpConnection.getContentType()));
            System.out.println(JSON.toJSONString(httpConnection.getRequestMethod()));
            System.out.println(JSON.toJSONString(httpConnection.getDoOutput()));
            e.printStackTrace();
        } finally {
            try {
                closeOutputStream(os, fis, bis);
                closeInputStream(is, br);
                closeUrlCon(httpConnection);
            } catch (Exception e2) {
                e2.printStackTrace();
            }
        }
        return retStr;
    }

    private HttpsURLConnection  init(String p_addr){
        try {
            URL url = new URL(null,p_addr, new sun.net.www.protocol.https.Handler());
            if (p_addr.contains("https://")) {
                //url = new URL(null, p_addr, new com.sun.net.ssl.internal.www.protocol.https.Handler());

                HttpsHandler.trustAllHttpsCertificates();
                HostnameVerifier hv = new HostnameVerifier() {
                    public boolean verify(String urlHostName, SSLSession session) {
                        return true;
                    }
                };
                HttpsURLConnection.setDefaultHostnameVerifier(hv);
                url = new URL(null,p_addr, new sun.net.www.protocol.https.Handler());
            }
            else{
                url = new URL(p_addr);
            }


                httpConnection = (HttpsURLConnection) url.openConnection();

        } catch (Exception e) {
            e.printStackTrace();
        }
        return  httpConnection;
    }
/*
    public String posts(String param,String requestAddr,String authorization,String length) throws Exception{
        URL url = new URL(requestAddr);
        HttpsURLConnection urlCon = (HttpsURLConnection) url.openConnection();


        urlCon.setHostnameVerifier(new HostnameVerifier() {
            public boolean verify(String paramString, SSLSession paramSSLSession) {
                return true;
            }
        });

        //创建SSLContext对象，并使用我们指定的信任管理器初始化
        TrustManager tm = new X509TrustManager() {
            public void checkClientTrusted(X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {
            }

            public void checkServerTrusted(X509Certificate[] paramArrayOfX509Certificate,
                                           String paramString) throws CertificateException {
            }

            public X509Certificate[] getAcceptedIssuers() {
                return null;
            }
        };

        javax.net.ssl.SSLContext sslContext = javax.net.ssl.SSLContext.getInstance("SSL", "SunJSSE");
        //读取证书文件
        X509Certificate client = toByteArray(clientCertPath);
        X509Certificate[] clientTrusted = new  X509Certificate[]{client};

        X509Certificate server = toByteArray(trustCertPath);
        X509Certificate[] serverTrusted = new  X509Certificate[]{server};
        ((X509TrustManager) tm).checkClientTrusted(clientTrusted,".PEM");
        ((X509TrustManager) tm).checkServerTrusted(serverTrusted,".PEM");
        sslContext.init(null, new TrustManager[]{tm}, new java.security.SecureRandom());

        //从上述SSLContext对象中得到SSLSocketFactory对象
        SSLSocketFactory ssf = sslContext.getSocketFactory();

        //创建HttpsURLConnection对象，并设置其SSLSocketFactory对象
        urlCon.setSSLSocketFactory(ssf);

        urlCon.setConnectTimeout(60000);
        urlCon.setRequestProperty("Accept-Encoding", "gzip,deflate");
        urlCon.setRequestProperty("Content-Type", "application/xml");
        urlCon.setRequestProperty("Authorization", authorization);
        urlCon.setRequestProperty("Content-Length", length);
        urlCon.setRequestProperty("Host", "tts.sandbox.apib2b.citi.com");
        urlCon.setRequestProperty("Connection", "Keep-Alive");
        urlCon.setRequestProperty("User-Agent", "Apache-HttpClient/4.1.1");
        urlCon.setDoOutput(true);
        urlCon.setDoInput(true);
        urlCon.setRequestMethod("POST");
        //urlCon.setRequestProperty("Content-type", "application/json");
        urlCon.setRequestProperty("Content-type", "text/plain");
        urlCon.setRequestProperty("charset", charset);

        OutputStreamWriter out = new OutputStreamWriter(urlCon.getOutputStream(), "UTF-8");
        out.write(param);
        out.flush();
        out.close();

        BufferedReader reader = new BufferedReader(new InputStreamReader(
                urlCon.getInputStream(), "UTF-8"));
        String tempLine = "";
        StringBuffer resultBuffer = new StringBuffer();
        while ((tempLine = reader.readLine()) != null) {
            resultBuffer.append(tempLine).append(System.getProperty("line.separator"));
        }
        return resultBuffer.toString();
    }*/

    /**
     * @param urlCon
     */
    private static void closeUrlCon(HttpsURLConnection urlCon) {
        if (urlCon != null) {
            urlCon.disconnect();
        }
    }

    /**
     * @param is
     * @param br
     * @throws IOException
     */
    private static void closeInputStream(InputStream is, BufferedReader br)
            throws IOException {
        if (br != null) {
            br.close();
        }
        if (is != null) {
            is.close();
        }
    }

    /**
     * @param os
     * @param fis
     * @param bis
     * @throws IOException
     */
    private static void closeOutputStream(OutputStream os, InputStream fis,
                                          BufferedInputStream bis) throws IOException {
        if (os != null) {
            os.flush();
        }
        if (bis != null) {
            bis.close();
        }
        if (fis != null) {
            fis.close();
        }
        if (os != null) {
            os.close();
        }
    }

    public String getTruestCertPwd() {
        return truestCertPwd;
    }

    public void setTruestCertPwd(String truestCertPwd) {
        this.truestCertPwd = truestCertPwd;
    }

    public String getClientCertPwd() {
        return clientCertPwd;
    }

    public void setClientCertPwd(String clientCertPwd) {
        this.clientCertPwd = clientCertPwd;
    }

    public String getClientCertPath() {
        return clientCertPath;
    }

    public void setClientCertPath(String clientCertPath) {
        this.clientCertPath = clientCertPath;
    }

    public String getTrustCertPath() {
        return trustCertPath;
    }

    public void setTrustCertPath(String trustCertPath) {
        this.trustCertPath = trustCertPath;
    }

    public String getTruestKeyType() {
        return truestKeyType;
    }

    public void setTruestKeyType(String truestKeyType) {
        this.truestKeyType = truestKeyType;
    }

    public String getClientKeyType() {
        return clientKeyType;
    }

    public void setClientKeyType(String clientKeyType) {
        this.clientKeyType = clientKeyType;
    }

    public static X509Certificate toByteArray(String filename) throws Exception {
        X509Certificate xc = null;
        CertificateFactory CF = null;
        FileInputStream in = null;
        try {
            CF = CertificateFactory.getInstance("X.509");
            in = new FileInputStream(filename);
            xc =(X509Certificate) CF.generateCertificate(in);

        } catch (IOException e) {
            e.printStackTrace();
            throw e;
        } finally {
            try {
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
            in.close();
        }
        return xc;
    }
}
